package com.cincc.cinccimdemo.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewGroup;

import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;

import com.cincc.cinccimdemo.R;
import com.cincc.cinccimdemo.common.Constants;
import com.cincc.cinccimdemo.common.callback.IVoiceCallback;

import java.util.LinkedList;

public class VoiceArcView extends ViewGroup {

    private static final String TAG = "VoiceArcView";
    Context context;

    int screenWidth, screenHeight;
    float mTop;
    int hLine, vLine, mLeft, mRight, mBottom;

    /**
     * 左边选项 的 坐标以及角度
     */
    private final float[] mLeftPosArray = new float[]{0, 0};
    private final float[] mLeftTanArray = new float[]{0, 0};

    /**
     * 右边选项的坐标以及角度
     */
    private final float[] mRightPosArray = new float[]{0, 0};
    private final float[] mRightTanArray = new float[]{0, 0};


    float cancelRecLeft, cancelRecTop;
    RectF cancelRect;
    int cancelRecWidth;

    RectF centerVoiceRect;

    RectF leftWaveRect = new RectF();
    RectF rightWaveRect = new RectF();
    Integer[] defaultVolumes = new Integer[]{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};

    LinkedList<Integer> volumes = new LinkedList<>();

    //当前状态
    private VoiceArcStatus mCurrentStatus = VoiceArcStatus.INIT;

    public VoiceArcView(Context context) {
        super(context);
        this.context = context;
    }

    public VoiceArcView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        //这里设置背景色和透明度，避免在XML里面设置造成子元素也透明的后果
        this.setBackgroundColor(getResources().getColor(R.color.chat_audio_voiceview_bg));
        this.getBackground().setAlpha(170);
        init();
    }

    private void init() {
        Point point = new Point();
        screenWidth = context.getResources().getDisplayMetrics().widthPixels;
        screenHeight = context.getResources().getDisplayMetrics().heightPixels;

        hLine = screenWidth / 2;
        vLine = screenHeight * 3 / 4;

        mLeft = -screenWidth / 2;
        mRight = screenWidth * 3 / 2;
        mTop = screenHeight * 3 / 4;
        mBottom = (screenHeight * 3 / 4) + (2 * screenWidth);

        /**
         * 初始化的框
         */
        RectF mRect = new RectF(mLeft, mTop - 200, mRight, mBottom - 200);

        /**
         * 左选项框的path
         */
        Path mLeftPath = new Path();
        mLeftPath.addArc(mRect, 250.0f, 10.0f);
        PathMeasure leftPathMeasure = new PathMeasure();
        leftPathMeasure.setPath(mLeftPath, true);
        leftPathMeasure.getPosTan(0.0f, mLeftPosArray, mLeftTanArray);

        /**
         * 右选项框的path
         */
        Path mRightPath = new Path();
        mRightPath.arcTo(mRect, 290.0f, -10.0f);//得反向来绘制
        PathMeasure rightPathMeasure = new PathMeasure();
        rightPathMeasure.setPath(mRightPath, true);
        rightPathMeasure.getPosTan(0.0f, mRightPosArray, mRightTanArray);

        // 绘制 中间 语音框
        centerVoiceRect = new RectF();
        float centerVoiceX = screenWidth / 2;
        float centerVoiceY = mRightPosArray[1];
        centerVoiceRect.left = centerVoiceX - 250;
        centerVoiceRect.right = centerVoiceX + 250;

        centerVoiceRect.top = centerVoiceY - 500;
        centerVoiceRect.bottom = centerVoiceY - 350;

        cancelRecWidth = 100;
        cancelRecLeft = screenWidth / 2 - cancelRecWidth / 2;
        cancelRecTop = mTop - 300;
        cancelRect = new RectF(cancelRecLeft, cancelRecTop, cancelRecLeft + cancelRecWidth, cancelRecTop + cancelRecWidth);

        resetList();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

    }

    VectorDrawableCompat bottomVoiceIcon = VectorDrawableCompat.create(getResources(), R.mipmap.conversation_audio_microphone1, null);
    Bitmap conversationCancelWhite = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.conversation_audio_close_white);
    Bitmap conversationCancelBlack = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.conversation_audio_close_black);


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawTop(canvas);
        drawBottom(canvas);
    }

    public void responseTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            doDownAction(event);
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            doMoveAction(event);
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            doUpAction(event);
        }
    }

    /**
     * 拦截录制离线语音的时候对该view的点击事件
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return true;
    }

    private void doDownAction(MotionEvent event) {
        mCurrentStatus = VoiceArcStatus.CENTER;
        startTime();
    }

    private void doUpAction(MotionEvent event) {
        Log.d(TAG, "doUpAction: ");
        stopRecord();
    }

    private void stopRecord() {
//        Boolean isCancel = isContains(event);
//        Log.d(TAG, "isContains: " + isCancel);
        if (mCurrentStatus == VoiceArcStatus.CENTER) {
            voiceCallback.onSuccess();
        } else {
            voiceCallback.onCancel();
        }
        mCurrentStatus = VoiceArcStatus.INIT;
        setVisibility(GONE);
        stopTime();
    }

    private void doMoveAction(MotionEvent event) {
        float xPos = event.getRawX();
        float yPos = event.getRawY();
        if (yPos > vLine) {
            if (xPos >= mRightPosArray[0]) {
                mCurrentStatus = VoiceArcStatus.RIGHT;
            } else if (xPos <= mLeftPosArray[0]) {
                mCurrentStatus = VoiceArcStatus.LEFT;
            } else {
                mCurrentStatus = VoiceArcStatus.CENTER;
            }
        } else {
            if (xPos >= hLine) {
                mCurrentStatus = VoiceArcStatus.RIGHT;
            } else {
                mCurrentStatus = VoiceArcStatus.LEFT;
            }
        }
        Log.d(TAG, "doMoveAction: xPos:" + xPos + " yPos:" + yPos + " vLine:" + vLine + " hLine:" + hLine + " mRightPosArray[0]:" + mRightPosArray[0]);
        invalidate();
    }

    /**
     * 绘制上半部分
     *
     * @param canvas
     */
    private void drawTop(Canvas canvas) {
        Log.d(TAG, "drawTop: mCurrentStatus " + mCurrentStatus);
        if (mCurrentStatus == VoiceArcStatus.CENTER) {
            drawText(canvas, getResources().getString(R.string.chat_tvAudio_send), mTop - 80);

            Paint cancelPaint = new Paint();
            cancelPaint.setColor(getResources().getColor(R.color.n300));
            cancelPaint.setAlpha(200);
            canvas.drawCircle(screenWidth / 2, cancelRecTop + cancelRecWidth / 2, cancelRecWidth / 2, cancelPaint);

            int conversationCancelWhiteWidth = conversationCancelWhite.getWidth();
            int conversationCancelWhiteHeight = conversationCancelWhite.getHeight();
            canvas.drawBitmap(conversationCancelWhite, cancelRecLeft + (cancelRecWidth - conversationCancelWhiteWidth) / 2, cancelRecTop + (cancelRecWidth - conversationCancelWhiteHeight) / 2, new Paint());

            drawWaveRec(canvas, Color.WHITE, Color.BLUE);
        } else if (mCurrentStatus == VoiceArcStatus.LEFT || mCurrentStatus == VoiceArcStatus.RIGHT) {
            drawText(canvas, getResources().getString(R.string.chat_tvAudio_cancel), cancelRecTop - 40);

            Paint cancelPaint = new Paint();
            cancelPaint.setColor(Color.WHITE);
            canvas.drawCircle(screenWidth / 2, cancelRecTop + cancelRecWidth / 2, cancelRecWidth / 2, cancelPaint);

            int conversationCancelBlackWidth = conversationCancelBlack.getWidth();
            int conversationCancelBlackHeight = conversationCancelBlack.getHeight();
            canvas.drawBitmap(conversationCancelBlack, cancelRecLeft + (cancelRecWidth - conversationCancelBlackWidth) / 2, cancelRecTop + (cancelRecWidth - conversationCancelBlackHeight) / 2, new Paint());

            drawWaveRec(canvas, getResources().getColor(R.color.chat_audio_voiceview_waverec), Color.WHITE);
        }
    }

    /**
     * 绘制文字部分 (松开 发送) 和 (松开 取消)
     *
     * @param canvas
     * @param content
     * @param top
     */
    private void drawText(Canvas canvas, String content, float top) {
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.cancel_text));
        paint.setTextSize(40);
        float textWidth = paint.measureText(content);
        canvas.drawText(content, screenWidth / 2 - textWidth / 2, top, paint);
    }

    /**
     * 绘制语音波浪框
     *
     * @param canvas
     * @param bgColor
     * @param waveColor
     */
    private void drawWaveRec(Canvas canvas, int bgColor, int waveColor) {
        int second = Constants.TOTAL_TIME - currentTime;
        if (second < 10 && second > 0) {
            drawVoiceRect(canvas, Color.WHITE);
            Paint paint1 = new Paint();
            paint1.setColor(getResources().getColor(R.color.n200));
            paint1.setTextSize(40);
            String content = (Constants.TOTAL_TIME - currentTime) + "\"" + getResources().getString(R.string.second_stop_record);

            Rect textRect = new Rect();
            paint1.getTextBounds(content, 0, content.length(), textRect);
            float centerX = (centerVoiceRect.right + centerVoiceRect.left) / 2 - textRect.width() / 2;
            float centerY = (centerVoiceRect.bottom + centerVoiceRect.top) / 2 + textRect.height() / 2;
            canvas.drawText(content, centerX, centerY, paint1);
        } else {
            drawVoiceRect(canvas, bgColor);
            drawWaveLine(canvas, waveColor);
        }
    }


    private void drawVoiceRect(Canvas canvas, int bgColor) {
        Paint paint = new Paint();
        paint.setColor(bgColor);
        canvas.drawRoundRect(centerVoiceRect, 20, 20, paint);
    }

    private Boolean isContains(MotionEvent event) {
        RectF targetRect = new RectF();
        targetRect.left = cancelRect.left - cancelRecWidth;
        targetRect.right = cancelRect.right + cancelRecWidth;
        targetRect.top = cancelRect.top - cancelRecWidth;
        targetRect.bottom = cancelRect.bottom + cancelRecWidth;
        return targetRect.contains(event.getRawX(), event.getRawY());
    }

    /**
     * 绘制下半部分
     *
     * @param canvas
     */
    private void drawBottom(Canvas canvas) {
        Path mRealPath = new Path();
        float realCenterX = screenWidth / 2;
        float realCenterY = screenWidth + mTop - 50;
        mRealPath.addCircle(realCenterX, realCenterY, screenWidth, Path.Direction.CW);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.chat_audio_voiceview_bg));
        paint.setAlpha(50);
        canvas.drawPath(mRealPath, paint);
        paint.setColor(getResources().getColor(R.color.circle_stokte));
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(4);
        canvas.drawPath(mRealPath, paint);

        canvas.save();
        int width = bottomVoiceIcon.getIntrinsicWidth();
        int height = bottomVoiceIcon.getIntrinsicHeight();

        bottomVoiceIcon.setBounds(0, 0, width, height);
        RectF mInnerRect = new RectF(mLeft, mTop - 120, mRight, mBottom - 80);
        canvas.translate(hLine - width / 2, mInnerRect.top + screenHeight / 8);
        bottomVoiceIcon.draw(canvas);
        canvas.restore();
    }

    /**
     * 根据语音分贝大小，画出波浪高度，目前是默认左右两边各20个，对称显示的这么一搞效果
     *
     * @param canvas
     * @param color
     */
    private void drawWaveLine(Canvas canvas, int color) {

        float centerX = (centerVoiceRect.right + centerVoiceRect.left) / 2;
        float centerY = (centerVoiceRect.bottom + centerVoiceRect.top) / 2;

        Paint paint = new Paint();
        float lineWidth = 5.0f;

        paint.setColor(color);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(2);
        paint.setAntiAlias(true);
        for (int i = 0; i < volumes.size(); i++) {
            //左边矩形
            leftWaveRect.left = centerX - (2 * i * lineWidth + 2 * lineWidth);
            leftWaveRect.top = centerY - volumes.get(i) * lineWidth / 2;
            leftWaveRect.right = centerX - (2 * i * lineWidth + lineWidth);
            leftWaveRect.bottom = centerY + volumes.get(i) * lineWidth / 2;
            canvas.drawRoundRect(leftWaveRect, 5.0f, 5.0f, paint);

            //右边矩形
            rightWaveRect.left = centerX + 2 * i * lineWidth + lineWidth;
            rightWaveRect.top = centerY - volumes.get(i) * lineWidth / 2;
            rightWaveRect.right = centerX + 2 * i * lineWidth + 2 * lineWidth;
            rightWaveRect.bottom = centerY + volumes.get(i) * lineWidth / 2;
            canvas.drawRoundRect(rightWaveRect, 5.0f, 5.0f, paint);
        }
    }

    private IVoiceCallback voiceCallback;

    public void setVoiceCallback(IVoiceCallback voiceCallback) {
        this.voiceCallback = voiceCallback;
    }

    /**
     * 根据录音实时返回的分贝值算出波浪高度，然后刷新页面
     *
     * @param value
     */
    public void setVoiceVolume(double value) {
        Log.d(TAG, "setVoiceVolume: value = " + value);
        int waveHeight = getWaveHeight(value);
        volumes.add(0, waveHeight);
        volumes.removeLast();
        invalidate();
    }

    /**
     * 根据分贝值算出波浪的高度
     *
     * @param db 分贝值
     * @return
     */
    private int getWaveHeight(double db) {
        if (db < 44) {
            return 3;
        } else if (db >= 44 && db < 52) {
            return 4;
        } else if (db >= 52 && db < 60) {
            return 6;
        } else if (db >= 60 && db < 68) {
            return 7;
        } else if (db >= 68 && db < 76) {
            return 9;
        } else if (db >= 76 && db < 84) {
            return 11;
        } else if (db >= 84 && db < 92) {
            return 13;
        } else {
            return 15;
        }
    }

    /**
     * 设置默认的波浪高度
     */
    private void resetList() {
        volumes.clear();
        for (int i = 0; i < defaultVolumes.length; i++) {
            volumes.add(defaultVolumes[i]);
        }
    }

    Handler mHandler = new Handler();
    MyRunnable mRunnable;
    //用以记录录音时长，用作倒计时用
    int currentTime = 0;

    private void startTime() {
        if (mRunnable == null) {
            mRunnable = new MyRunnable();
            mHandler.postDelayed(mRunnable, 1000);
        }
    }

    private void stopTime() {
        currentTime = 0;
        mHandler.removeCallbacks(mRunnable);
        mRunnable = null;
    }

    private class MyRunnable implements Runnable {
        @Override
        public void run() {
            currentTime++;
            int second = Constants.TOTAL_TIME - currentTime;
            if (second < 10 && second > 0) {
                invalidate();
            }
            if (Constants.TOTAL_TIME == currentTime) {
                stopRecord();
            } else {
                mHandler.postDelayed(this, 1000);
            }
        }
    }
}
